/*
    Copyright (C) 2008  Helmut Juskewycz

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package com.juskewycz.dividere.action.split;

import com.juskewycz.dividere.action.IProgressListener;
import com.juskewycz.dividere.action.IProgressObserverable;
import com.juskewycz.dividere.action.ProgressStatus;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Implements some default behavior of a splitter like adding/removing listeners
 * and some error handling. This class also adds <code>IProgressObserverable</code>
 * as an interface. This allows to observe the progress of the process.
 * 
 * @author Helmut Juskewycz
 * @createdon 27. January 2008
 * @lastmodified 27. January 2008
 * @history
 * 27. January 2008 Finished version 1.0
 */
public abstract class ASplitter implements ISplitter, IProgressObserverable {

    private static final Logger logger = Logger.getLogger(ASplitter.class.getName());

    protected static final int ONE_MB = 1048576;
    protected static final int BUFF_SIZE = (ONE_MB * 4);
    protected static final byte[] buffer = new byte[BUFF_SIZE];
    protected final List<ISplitListener> splitListeners = new ArrayList<ISplitListener>(1);
    protected final List<IProgressListener> progressListeners = new ArrayList<IProgressListener>(1);

    protected void notifyProgressListeners(ProgressStatus status) {
	for (IProgressListener iProgressListener : progressListeners) {
	    iProgressListener.update(status);
	}
    }

    protected void notifySplitBegin(File originalFile) {
	for (ISplitListener iSplitListener : splitListeners) {
	    iSplitListener.splitBegin(originalFile);
	}
    }

    protected void notifySplitEnd(File originalFile) {
	for (ISplitListener iSplitListener : splitListeners) {
	    iSplitListener.splitEnd(originalFile);
	}
    }

    protected void notifySplitPartBegin(int number, File partFile) {
	for (ISplitListener iSplitListener : splitListeners) {
	    iSplitListener.splitPartBegin(number, partFile);
	}
    }

    protected void notifySplitPartEnd(int number, File partFile) {
	for (ISplitListener iSplitListener : splitListeners) {
	    iSplitListener.splitPartEnd(number, partFile);
	}
    }

    protected void notifyError(ProgressStatus status) {
	for (IProgressListener iProgressListener : progressListeners) {
	    iProgressListener.error(status);
	}
    }

    protected boolean validSplitterInputArgumtents(String filePath, long splitSize) {
	if (filePath == null) {
	    notifyError(new ProgressStatus(0, 0, ERROR_SPLIT_FILE_PATH_NULL, true));
	    Logger.getLogger(ASplitter.class.getName()).log(Level.SEVERE, ERROR_SPLIT_FILE_PATH_NULL);
	    return false;
	}

	if (splitSize <= 0) {
	    notifyError(new ProgressStatus(0, 0, ERROR_SPLIT_SIZE_INVALID, true));
	    logger.log(Level.SEVERE, ERROR_SPLIT_SIZE_INVALID);
	    return false;
	}
	return true;
    }

    protected boolean checkSplitFileExists(File originalFile) {
	if (!originalFile.exists()) {
	    notifyError(new ProgressStatus(0, 0, ERROR_SPLIT_FILE_NOT_EXISTS, true));
	    logger.log(Level.SEVERE, ERROR_SPLIT_FILE_NOT_EXISTS);
	    return false;
	}
	return true;
    }

    protected void errorCanNotCreatePartFile(String filePath, int piecesNumber, int pieceNumber) {
	notifyError(new ProgressStatus(pieceNumber, piecesNumber, ERROR_CANT_CREATE_PART_FILE, true));
	logger.log(Level.SEVERE, ERROR_CANT_CREATE_PART_FILE);
	return;
    }

    protected String createSplitFilePath(String path, int pieceNumber) {
	StringBuilder sb = new StringBuilder(path);
	sb.append(".");
	sb.append(String.format("%03d", pieceNumber));
	return sb.toString();
    }

    public void addListener(ISplitListener listener) {
	splitListeners.add(listener);
    }

    public void removeListener(ISplitListener listener) {
	splitListeners.remove(listener);
    }

    public void addListener(IProgressListener listener) {
	progressListeners.add(listener);
    }

    public void removeListener(IProgressListener listener) {
	progressListeners.remove(listener);
    }
}
